package com.zx.framework.core.util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;


public class ClassesUtil
{
	/**
	 * 从包package中获取所有的Class,遍历子包
	 * 
	 * @param pack
	 * @return
	 * @throws ClassNotFoundException 
	 * @throws UnsupportedEncodingException 
	 */
	public static List<Class<?>> getClasses(String packagePath) throws ClassNotFoundException, UnsupportedEncodingException
	{
		List<Class<?>> classes = new ArrayList<Class<?>>();
		String packageName = packagePath.replace(".", File.separator);

		URL url = Thread.currentThread().getContextClassLoader().getResource(
				packageName);
		if(url==null)
		{
			return classes;
		}
		// 处理路径中的中文信息
		File baseFile = new File(URLDecoder.decode(url.getFile(),"utf-8"));
		if (!baseFile.exists())
		{
			// 给出的类包不存在的情况下
			return classes;
		}
		if(baseFile.list().length==0)
		{
			return classes;
		}
		// 如果存在 就获取包下的所有文件 包括目录
		File[] files = baseFile.listFiles(new FileFilter()
		{		
			public boolean accept(File file)
			{
				return ( file.isDirectory()) || (file.getName().endsWith(".class"));
			}
		});
		if(files!=null)
		{
			for (int i = 0; i < files.length; i++)
			{
				File tempFile = files[i];
				if(tempFile.isDirectory())
				{
					classes.addAll(getClasses(packagePath + "." + tempFile.getName()));
				}else
				{
					String className = tempFile.getName().substring(0, tempFile.getName().length() - 6);
					classes.add(Class.forName(packagePath + '.' + className));
				}
			}
		}
		return classes;
	}
	
	/**
	 * 获取接口的所有实现
	 * @author wangguowei
	 * 
	 * @param c
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List<Class<?>> getAllClassByInterface(Class c) {
		List<Class<?>> returnClassList = new ArrayList<Class<?>>(); // 返回结果
		// 如果不是一个接口，则不做处理
		if (c.isInterface()) {
			String packageName = c.getPackage().getName(); // 获得当前的包名
			try {
				List<Class<?>> allClass = getClasses(packageName); // 获得当前包下以及子包下的所有类
				// 判断是否是同一个接口
				for (int i = 0; i < allClass.size(); i++) {
					if (c.isAssignableFrom(allClass.get(i))) { // 判断是不是一个接口
						if (!c.equals(allClass.get(i))) { // 本身不加进去
							returnClassList.add(allClass.get(i));
						}
					}
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return returnClassList;
	}
}
